/*
Copyright 2010 Iain Surgey.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#define REF_VERSION     0.01

#define SPANDIV 16
#define SPANDIV_SHIFT 4
#define SPANDIV_MASK 0xFFFFFFF0

#define AMBILIGHT 0.99

#define	MAX_MAP_MODELS		1024
#define	MAX_MAP_BRUSHES		8192
#define	MAX_MAP_ENTITIES	2048
#define	MAX_MAP_ENTSTRING	0x40000
#define	MAX_MAP_TEXINFO		8192

#define	MAX_MAP_AREAS		256
#define	MAX_MAP_AREAPORTALS	1024
#define	MAX_MAP_PLANES		65536
#define	MAX_MAP_NODES		65536
#define	MAX_MAP_BRUSHSIDES	65536
#define	MAX_MAP_LEAFS		65536
#define	MAX_MAP_VERTS		65536
#define	MAX_MAP_FACES		65536
#define	MAX_MAP_LEAFFACES	65536
#define	MAX_MAP_LEAFBRUSHES 65536
#define	MAX_MAP_PORTALS		65536
#define	MAX_MAP_EDGES		128000
#define	MAX_MAP_SURFEDGES	256000
#define	MAX_MAP_LIGHTING	0x200000
#define	MAX_MAP_VISIBILITY	0x100000

#define XCENTERING      (1.0 / 2.0)
#define YCENTERING      (1.0 / 2.0)

#define M_PI		3.141592654
#define M_PI2		6.283185307
#define M_PI2_360	0.017453293

#define MAXHEIGHT       1200
#define MAXWIDTH        1600

#define BACKFACE_EPSILON        0.01
#define NEAR_CLIP       0.01

#define	SURF_SKY		0x4		// don't draw, but add to skybox
#define	SURF_WARP		0x8		// turbulent water warp
#define	SURF_TRANS33	0x10
#define	SURF_TRANS66	0x20
#define	SURF_FLOWING	0x40	// scroll towards angle
#define	SURF_NODRAW		0x80	// don't bother referencing the texture*/

#define	SURF_PLANEBACK		2
#define	SURF_DRAWSKY		4
#define SURF_DRAWTURB		0x10
#define SURF_FLOW			0x100
#define SURF_DRAWSKYBOX		0x80
#define SURF_DRAWBACKGROUND	0x40

#define FULLY_CLIPPED_CACHED	0x80000000
#define FRAMECOUNT_MASK			0x7FFFFFFF

#define PITCH	0	// up / down
#define YAW		1	// left / right
#define ROLL	2	// fall over

#define NUM_MIPS	4

#define NUMSTACKEDGES           5000
#define NUMSTACKSURFACES        5000
#define MAXSPANS                30000

#define ALIAS_VERSION	8

#define	MAX_TRIANGLES	4096
#define MAX_VERTS		2048
#define MAX_FRAMES		512
#define MAX_MD2SKINS	32
#define	MAX_SKINNAME	64
#define MAXALIASVERTS   2000

#define MAX_LBM_HEIGHT  480

#define BBOX_TRIVIAL_ACCEPT 0
#define BBOX_MUST_CLIP_XY   1
#define BBOX_MUST_CLIP_Z    2
#define BBOX_TRIVIAL_REJECT 8

#define ALIAS_Z_CLIP_PLANE      				4
#define ALIAS_LEFT_CLIP                         0x0001
#define ALIAS_TOP_CLIP                          0x0002
#define ALIAS_RIGHT_CLIP                        0x0004
#define ALIAS_BOTTOM_CLIP                       0x0008
#define ALIAS_Z_CLIP                            0x0010
#define ALIAS_XY_CLIP_MASK                      0x000F

struct
{
	vec3          normal;
	float           dist;
	clipplane_t     *next;
	byte            leftedge;
	byte            rightedge;
	byte            reserved[2];
} clipplane_t;

clipplane_t view_clipplanes[4];

mleaf_t	*r_viewleaf;
int	r_viewcluster, r_oldviewcluster;
int		r_visframecount;

float	vieworg[3];
float	viewangles[3];

float	r_origin[3];
float	modelorg[3];

float	vec_origin[3];

float   r_aliasuvscale;
float   xOrigin, yOrigin;
float   xcenter, ycenter;
float   xscale, yscale;
float   xscaleinv, yscaleinv;
float   xscaleshrink, yscaleshrink;
float   verticalFieldOfView;
float   horizontalFieldOfView;
float	fov_x, fov_y;
int		scr_x, scr_y, scr_width, scr_height;
float    aliasxscale, aliasyscale, aliasxcenter, aliasycenter;

mplane_t        screenedge[4];

int  r_frustum_indexes[24];
int  *pfrustum_indexes[4];

int ord_aliasvrect_x, ord_aliasvrect_y, ord_aliasvrect_width, ord_aliasvrect_height;
int                     ord_vrectright, ord_vrectbottom;        // right & bottom screen coords
int                     ord_aliasvrectright, ord_aliasvrectbottom;      // scaled Alias versions
float           ord_vrectrightedge;                 // rightmost right edge we care about,
									//  for use in edge list
float           ord_fvrectx, ord_fvrecty;               // for floating-point compares
float           ord_fvrectx_adj, ord_fvrecty_adj; // left and top edges, for clamping
int                     ord_vrect_x_adj_shift20;    // (vrect.x + 0.5 - epsilon) << 20
int                     ord_vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20
float           ord_fvrectright_adj, ord_fvrectbottom_adj;
									// right and bottom edges, for clamping
float           ord_fvrectright;                    // rightmost edge, for Alias clamping
float           ord_fvrectbottom;                   // bottommost edge, for Alias clamping
									// 2.0 = 90 degrees


int  vrect_x,vrect_y,vrect_width,vrect_height;

struct
{
	medge_t                 *owner;
	int               u;				// 0
	int               u_step;			// 4
	edge_t   *prev, *next;				// 8,12
	int  surfs[2];						// 16
	edge_t   *nextremove;				// 24
	float                   nearzi;		// 28
			// 32
} edge_t;						//total	   36

int r_lightwidth, r_lightptr;


// FIXME: compress, make a union if that will help
// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
struct
{
	surf_t   *next;                  // active surface stack in r_edge.c
	surf_t   *prev;                  // used in r_edge.c for active surf stack
	espan_t  *spans;                 // pointer to linked list of spans to draw
	int                     key;                            // sorting key (BSP order)
	int                     last_u;                         // set during tracing
	int                     spanstate;                      // 0 = not in span
									// 1 = in span
									// -1 = in inverted span (end before
									//  start)
	int                     flags;                          // currentface flags
	msurface_t      *msurf;
	int entity;
	float           nearzi;                         // nearest 1/z on surface, for mipmapping
	int        insubmodel;
	float           d_ziorigin, d_zistepu, d_zistepv;

	int                     pad[2];                         // to 64 bytes - IS BITSHIFT ACTUALLY FASTER??
} surf_t;

float *tmorg;
float *vright_tex;
float *vup_tex;
float *vpn_tex;

struct
{
	int                             u, v, count;
	espan_t  *pnext;
} espan_t;

int r_framecount;
int r_zframe;
int r_zmmframe;


vec3 r_entorigin;
vec3 vup, base_vup;
vec3 vpn, base_vpn;
vec3 vright, base_vright;

int      c_faceclip;
int		 c_drawnode;
int      r_polycount;
int      r_drawnpolycount;
int      r_amodels_drawn;
int      r_outofsurfaces;
int      r_outofedges;

int      d_minmip;
float	d_scalemip0, d_scalemip1, d_scalemip2;

edge_t r_edges[NUMSTACKEDGES+1];
surf_t surfaces[NUMSTACKSURFACES+1];
espan_t basespans[MAXSPANS+1];

surf_t  *surface_p, *surf_max;
edge_t  *edge_p, *edge_max;
espan_t	*span_p, *max_span_p;

edge_t  *newedges[MAXHEIGHT];
edge_t  *removeedges[MAXHEIGHT];

int              r_currentkey;

amodel_t *s_pmdl;

struct {
	int           u, v, s, t;
	int             l;
	int             zi;
	int             flags;
	float   xyz[3];         // eye space
} finalvert_t;

struct
{
	int 						pskin;
	int                                     pskindesc;
	int                                     skinwidth;
	int                                     skinheight;
	triangle_t                     *ptriangles;
	finalvert_t                     *pfinalverts;
	int                                     numtriangles;
	int                                     drawtype;
	int                                     seamfixupX16;
	byte                       do_vis_thresh;
	int                                     vis_thresh;
} affinetridesc_t;

finalvert_t *atriparms_a, *atriparms_b, *atriparms_c;

int      ubasestep, errorterm, erroradjustup, erroradjustdown;

// r_edge.c -----------------------------------

edge_t	edge_head;
edge_t	edge_tail;
edge_t	edge_aftertail;
edge_t	edge_sentinel;

int	edge_head_u_shift20, edge_tail_u_shift20;
int	current_iv;

espan_t	*basespan_p;

float			transformed_modelorg[3];

float	DCG_p_taxis[3];
float 	DCG_p_saxis[3];
float	DCG_p_temp1[3];

msurface_t		*pface;

float    d_sdivzstepu, d_tdivzstepu, d_zistepu;
float    d_sdivzstepv, d_tdivzstepv, d_zistepv;
float    d_sdivzorigin, d_tdivzorigin, d_ziorigin;

int       sadjust, tadjust;
int		  sadjustl, tadjustl;

int              cachewidth, cacheheight, cw16, ch16;
int  			 cacheblock;
int 			 mshift, cwid;

model_t *currentmodel;

#__body__

